import Vue from 'vue'

import { Message } from 'element-ui'

let axioz = null

class RequestError extends Error {
  constructor(code, message) {
    super(message)
    this.code = code
    this.message = message
  }
}

const methods = ['get', 'post', 'put', 'delete']
const injectMethods = ($axios) => {
  for (const m of methods) {
    if (m === 'get') {
      const $m = $axios[m]
      $axios[m] = (url, params, option = {}) => {
        option.params = params
        return $m(url, option)
      }
    }
  }

  return $axios
}

// 替换地址中的参数
const matchUrlParams = (url, params = {}, encode = false) => {
  const keys = Object.keys(params)
  if (keys.length > 0) {
    keys.forEach((key) => {
      if (encode) {
        params[key] = encodeURIComponent(params[key])
      }
      if (url.includes(`:${key}`)) {
        url = url.replace(new RegExp(`:${key}`), params[key])
        delete params[key]
      }
    })
  }

  return { url, params }
}

export default function ({ $axios, redirect, store }) {
  $axios.onRequest((config) => {
    // console.log('on request:', config)
    if (config.method === 'get') {
      // 处理get请求参数
      const { url, params } = matchUrlParams(config.url, config.params)
      config.url = url
      config.params = params
    } else {
      // 处理非get请求参数
      const { url, params } = matchUrlParams(config.url, { ...config.data })
      config.url = url
    }
    // config.headers['Accept-Language'] = store.state.i18n.locale || 'zh'
    if (store.state.user.token) {
      config.headers.Authorization = `Bearer ${store.state.user.token}`
    }
  })

  $axios.onResponse((response) => {
    // console.log('response:', response)
    if (response.status !== 200 || !response.data || response.data.code !== 0) {
      const code = (response.data && response.data.code) || response.status
      const message =
        (response.data && response.data.message) || response.statusText
      const error = new RequestError(code, message)
      return Promise.reject({ code, message })
    }
    // TODO: 读取刷新的token
    // 刷新token
    if ('authorization' in response.headers) {
      const [_, token] = response.headers.authorization.split(' ')
      store.dispatch('user/setToken', token)
    }
    return Promise.resolve({ data: response.data?.data, error: null })
  })

  $axios.onError((error) => {
    // console.log('on error:', error)
    let code = error.code
    if (!code) {
      code = parseInt(error.response && error.response.status)
    }
    if (code === 400) {
      redirect('/400')
    }
    if (process.client) {
      Message.error(error.message)
    }

    return Promise.resolve({ data: null, error })
  })

  axioz = injectMethods($axios)
}

export { axioz }
